using System;
using System.Collections.Generic;
using System.Text;
using Sixeyed.CacheAdapter.Interfaces;
using Sixeyed.CacheAdapter.Helpers;
using System.Collections;
using System.IO;

namespace Sixeyed.CacheAdapter.Bases
{
    /// <summary>
    /// Base class for cache provider wrappers
    /// </summary>
    /// <typeparam name="TCacheProviderConfiguration">Configuration type</typeparam>
    public abstract class BaseCacheProvider<TCacheProviderConfiguration> : ICacheProvider
        where TCacheProviderConfiguration : ICacheProviderConfiguration
    {
        /// <summary>
        /// Gets/sets the configuration for a cache instance
        /// </summary>
        public abstract TCacheProviderConfiguration Configuration { get; set;}

        /// <summary>
        /// Gets whether the cache instance has been initialized
        /// </summary>
        public abstract bool IsInitialized { get; }

        /// <summary>
        /// Initializes the cache instance
        /// </summary>
        /// <param name="configuration">Cache instance configuration</param>
        public abstract void Initialize(ICacheProviderConfiguration configuration);

        /// <summary>
        /// Inserts or updates an object in the cache
        /// </summary>
        /// <param name="cacheKey">Lookup key for the object</param>
        /// <param name="serializableObject">Object to cache</param>
        public abstract void Put(string cacheKey, object serializableObject);

        /// <summary>
        /// Inserts or updates an object in the cache with a specified lifespan
        /// </summary>
        /// <param name="cacheKey">Lookup key for the object</param>
        /// <param name="serializableObject">Object to cache</param>
        /// <param name="lifespan">Expiration lifespan of the object</param>
        public abstract void Put(string cacheKey, object serializableObject, TimeSpan lifespan);

        /// <summary>
        /// Returns an object from the cache
        /// </summary>
        /// <param name="cacheKey">Lookup key for the object</param>
        /// <returns>Cached object, or null if not in cache</returns>
        public abstract object Get(string cacheKey);

        /// <summary>
        /// Removes an object from the cache
        /// </summary>
        /// <param name="cacheKey">Lookup key for the object</param>
        public abstract void Remove(string cacheKey);

        /// <summary>
        /// Gets an enumerator over all objects in the cache
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerator GetEnumerator();

        /// <summary>
        /// Returns a typed object from the cache
        /// </summary>
        /// <typeparam name="T">Object type</typeparam>
        /// <param name="cacheKey">Lookup key for the object</param>
        /// <returns>Cached object, or null if not in cache</returns>
        public T Get<T>(string cacheKey) 
            where T : class
        {
            return Get(cacheKey) as T;
        }        

        /// <summary>
        /// Returns a cache key as a hash of the given object
        /// </summary>
        /// <param name="objectBuffer">Object byte array</param>
        /// <returns>Cache key</returns>
        public virtual string GetCacheKey(byte[] objectBuffer)
        {
            return GuidHelper.GenerateGuid(objectBuffer).ToString();
        }

        /// <summary>
        /// Returns a cache key as a hash of the given object
        /// </summary>
        /// <param name="serializedObject">Serialized object string</param>
        /// <returns>Cache key</returns>
        public virtual  string GetCacheKey(string serializedObject)
        {
            return GuidHelper.GenerateGuid(serializedObject).ToString();
        }

        /// <summary>
        /// Returns a cache key as a hash of the given object
        /// </summary>
        /// <param name="serializableObject">Serialiazable object</param>
        /// <returns>Cache key</returns>
        public virtual string GetCacheKey(object serializableObject)
        {
            return GuidHelper.GenerateGuid(serializableObject).ToString();
        }

        /// <summary>
        /// Returns a random unique cache key
        /// </summary>
        /// <returns>Cache key</returns>
        public virtual string GetCacheKey()
        {
            return Guid.NewGuid().ToString();
        }

        /// <summary>
        /// Returns the type of the provider configuration
        /// </summary>
        /// <returns>Configuration type</returns>
        public Type GetConfigurationType()
        {
            return typeof(TCacheProviderConfiguration);
        }
    }
}
